home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / XML / Wddx.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  12.2 KB  |  451 lines

  1. <?php
  2. /**
  3.  * XML_Wddx : WDDX serializer and deserializer (works with or without the wddx extension)
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   XML
  14.  * @package    XML_Wddx
  15.  * @author     Alan Knowles <alan@akbkhome.com>
  16.  * @copyright  1997-2005 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    $Id: Wddx.php,v 1.8 2005/03/30 02:44:56 alan_k Exp $
  19.  * @link       http://pear.php.net/package/XML_Wddx
  20.  *
  21.  *
  22.  * @abstract
  23.  * serialization is done by   $string = XML_Wddx::serialize($data);
  24.  * deserialization is done by $data   = XML_Wddx::deserialize($string);
  25.  *
  26.  */
  27.  
  28. require_once 'XML/Parser.php';
  29.  
  30. class XML_Wddx extends XML_Parser {
  31.  
  32.  
  33.     /**
  34.     * 
  35.     *
  36.     * serialize a value
  37.     * usage:
  38.     *       echo XML_Wddx::serialize($array);
  39.     * 
  40.     * @param   mixed    value to serialize
  41.     * 
  42.     *
  43.     * @return   string   Serialize data.
  44.     * @access   public
  45.     * @static
  46.     */
  47.   
  48.  
  49.     function serialize($value) 
  50.     {
  51.         $x = new XML_Wddx;
  52.         return  "<wddxPacket version='1.0'><header/><data>\n". 
  53.             $x->indent(1) . trim($x->_serializeValue($value)) . "\n". 
  54.             $x->indent(-1) . "</data></wddxPacket>\n";
  55.     }
  56.     
  57.     /**
  58.     * 
  59.     *
  60.     * de-serialize a value (uses wddx_deserialize if it is built in..)
  61.     * usage:
  62.     *       echo XML_Wddx::deserialize($some_wddx_data);
  63.     * 
  64.     * @param   mixed    value to serialize
  65.     * 
  66.     *
  67.     * @return   mixed   deserialized data..
  68.     * @access   public
  69.     * @static
  70.  
  71.     */
  72.     
  73.     function deserialize($data) 
  74.     {
  75.         if (function_exists('wddx_deserialize')) {
  76.             return wddx_deserialize($data);
  77.         }
  78.         $t = &new XML_Wddx;
  79.         $t->XML_Parser();
  80.         
  81.         $t->parseString($data);
  82.         return $t->result['data'];
  83.     }
  84.     
  85.     
  86.     /**
  87.     * The core method.. that serializes data.
  88.     * 
  89.     * @param   mixed  value to serialize
  90.     *
  91.     * @return   string   serialized value.
  92.     * @access   private
  93.     * @see      see also methods.....
  94.     */
  95.   
  96.     
  97.     function _serializeValue($value) 
  98.     {
  99.         switch (gettype($value)) {
  100.             case 'string':
  101.                 if ( is_numeric ($value) &&  (intval(0+$value) ==  $value) )   {
  102.                     return "<number>$value</number>";
  103.                 }    
  104.                 //$this->indent(1);
  105.                 return  preg_match('/[^a-z0-9_ ]/i',$value) ? 
  106.                     "\n".$this->indent(0).'<string><![CDATA['.$value."]]></string>\n" : 
  107.                     "<string>$value</string>";
  108.                 //$this->indent(-1);
  109.                 
  110.             case 'integer':
  111.             case 'float':
  112.             case 'double':
  113.                 return "<number>$value</number>";
  114.                 
  115.             case 'boolean':
  116.                 return  sprintf("<boolean value='%s'/>",$value ? 'true':'false');
  117.  
  118.             case 'object':
  119.                 // sleep - ignored ATM
  120.                 $ret = "\n".$this->indent()."<struct>\n".
  121.                     $this->indent(1)."<var name='php_class_name'><string>".get_class($value)."</string></var>\n";
  122.                 
  123.                 foreach(get_object_vars($value) as $k=>$v) {
  124.                     $ret .= $this->indent(0).sprintf("<var name='%s'>",$k);
  125.                     $this->indent(1);
  126.                     $ret .= $this->_serializeValue($v);
  127.                     $this->indent(-1);
  128.                     $ret .= ($ret{strlen($ret)-1} == "\n") ? $this->indent() : '';
  129.                     $ret .= "</var>\n";
  130.                 }
  131.                 
  132.                 $this->indent(-1);
  133.                 return $ret .  $this->indent() . "</struct>\n"; 
  134.                 
  135.             case 'array':
  136.  
  137.                 $is_struct = (array_keys($value) !== range(0,sizeof($value)-1));
  138.                 $ret = "\n".$this->indent();
  139.                 $ret .= $is_struct ? "<struct>\n" : sprintf("<array length='%d'>",count($value)). "\n";
  140.                 $this->indent(1);
  141.                 foreach($value as $k=>$v) {
  142.                     $ret .= $this->indent(0);
  143.                     $ret .= $is_struct ? sprintf("<var name='%s'>",$k) : '';
  144.                     $this->indent(1);
  145.                     $ret .= $this->_serializeValue($v) ;
  146.                     $this->indent(-1);
  147.                     $ret .= ($ret{strlen($ret)-1} == "\n") ? $this->indent() : '';
  148.                     $ret .= $is_struct ? "</var>\n" : "\n";
  149.                 }
  150.                 
  151.                 $ret .= $this->indent(-1);
  152.                 $ret .= $is_struct ? '</struct>' : '</array>';
  153.                 return $ret . "\n";
  154.             case 'resource': // BIG KLUDGE!!!!
  155.             case 'NULL':
  156.                 return  "<null/>";
  157.                
  158.             default:
  159.                 echo "not handled " . gettype($value);
  160.                 exit;
  161.  
  162.         }
  163.         
  164.     }
  165.     
  166.         
  167.     /**
  168.     * Current indent level.
  169.     *
  170.     * @var int level
  171.     * @access private
  172.     */
  173.     var $_indent = 0;
  174.     
  175.     
  176.     
  177.     /**
  178.     * get an indent string
  179.     * 
  180.     * @param   int change (indent increment or decrement)
  181.     * 
  182.     * @return   string spaces 
  183.     * @access   private
  184.     */
  185.   
  186.     function indent($add=0) 
  187.     {
  188.         $this->_indent += $add;
  189.         if ($add < 0) { // should not happen!!
  190.             $add = 0;
  191.         }
  192.         return str_repeat('  ',$this->_indent);
  193.     }
  194.     
  195.     
  196.       
  197.     /**
  198.     * expat start handler.
  199.     * 
  200.     * @return   none
  201.     * @access   private
  202.     * @see      XML_Parser:startHandler
  203.     */
  204.     function startHandler($xp, $element, $attribs) 
  205.     {    
  206.         $ent = array('type'=>strtolower($element));
  207.        // echo "S:";print_r(func_get_args());
  208.       
  209.         switch (strtolower($element)) {
  210.             case 'wddxpacket':
  211.             case 'header':
  212.                 break;
  213.             case 'string':
  214.             case 'binary':
  215.                 $ent['data'] = '';
  216.                 array_push($this->_stack,$ent);
  217.                 break;
  218.             
  219.             case 'number':
  220.                 $ent['data'] = 0;
  221.                 array_push($this->_stack,$ent);
  222.                 break;
  223.             case 'boolean':
  224.                 $ent['data'] = false;
  225.                 array_push($this->_stack,$ent);
  226.                 break;
  227.             case 'null':
  228.                 $ent['data'] = null;
  229.                 array_push($this->_stack,$ent);
  230.                 break;
  231.                 
  232.                 
  233.             case 'char':
  234.                 if (isset($attribs['CODE'])) {
  235.                     $e = $this->_stackTop();
  236.                     $e['data'] .= chr(hexdec($attribs['CODE']));
  237.                     $this->_stackTop($e);
  238.                 }
  239.                 break;
  240.             
  241.             case 'struct':
  242.             case 'array':
  243.                 $ent['data'] = array();
  244.                 array_push($this->_stack,$ent);
  245.                 break;
  246.             case 'var':
  247.                 $ent['name'] = @$attribs['NAME'];
  248.                 
  249.                 array_push($this->_stack,$ent);
  250.                 break;
  251.             case 'recordset':
  252.                 break; // not handled yet...
  253.         }
  254.         
  255.         //echo "STACK:";print_r($this->stack);
  256.         //echo "S:";print_r(func_get_args());
  257.     }
  258.     /**
  259.     * expat end handler.
  260.     * 
  261.     * @return   none
  262.     * @access   private
  263.     * @see      XML_Parser:startHandler
  264.     */
  265.     function endHandler($xp, $element) 
  266.     {        
  267.         //echo "E:";print_r(func_get_args());
  268.     
  269.         if (!count($this->_stack)) {
  270.             return;
  271.         }
  272.         $parent = null;
  273.         switch (strtolower($element)) {
  274.             case 'packet':
  275.       
  276.             
  277.             case 'char':
  278.             case 'recordset':
  279.                 return;
  280.                 
  281.                 
  282.             case 'string':
  283.             case 'binary':
  284.             case 'number':
  285.             case 'boolean':
  286.             case 'null':
  287.             case 'array':
  288.             case 'struct':
  289.             case 'var':
  290.                 
  291.  
  292.                 $ent = array_pop($this->_stack);
  293.                 $parent = false;
  294.                 $parent = $this->_stackTop();
  295.                 if (!$parent) {
  296.                     $this->result = $ent;
  297.                     break;
  298.                 }
  299.                 
  300.                 // if this is a struct + php_class_name is set...
  301.                 if (($ent['type'] == 'struct') && isset($ent['data']['php_class_name'])) {
  302.                     $class = $ent['data']['php_class_name'];
  303.                     $obj = new $class;
  304.                     unset($ent['data']['php_class_name']);
  305.                     foreach($ent['data'] as $k=>$v) {
  306.                     
  307.                         $obj->$k = $v;
  308.                     }
  309.                     $ent['data'] = $obj;
  310.                 }
  311.                 
  312.                 
  313.                 // add ent to parent...
  314.                 
  315.                 if ($parent['type'] == 'var') {
  316.                     $parent['data'] = $ent['data'];
  317.                     break;
  318.                 }
  319.                 
  320.                 if ($ent['type'] == 'var') {
  321.                     if ($parent['type'] == 'struct') {
  322.                         if ($ent['name']) {
  323.                             $parent['data'][$ent['name']] = $ent['data'];
  324.                         } else {
  325.                             $parent['data'][] = $ent['data'];
  326.                         }
  327.                         break;
  328.                     }
  329.                 }
  330.                 if ($parent['type'] == 'array') {
  331.                     $parent['data'][] = $ent['data'];
  332.                     break;
  333.                 }
  334.                 
  335.                 $parent['data'] = $ent['data'];
  336.                 
  337.                 
  338.                 break;
  339.                 
  340.         } 
  341.         // put it back .. 
  342.         $this->_stackTop($parent);
  343.     
  344.        // echo "STACK:";print_r($this->stack);
  345.     
  346.     
  347.         //echo "E:";print_r(func_get_args());
  348.     }
  349.     
  350.     /**
  351.     * expat cdata handler.
  352.     * 
  353.     * @return   none
  354.     * @access   private
  355.     * @see      XML_Parser:cdataHandler
  356.     */
  357.     function cdataHandler($xp, $cdata)      
  358.     {    
  359.         //$ent = array('type'=>false);
  360.         if (!count($this->_stack)) {
  361.             return;
  362.         }
  363.     
  364.         $ent = $this->_stackTop();
  365.         
  366.         //var_dump($ent);
  367.         switch($ent['type']) {
  368.             case 'string':
  369.             case 'binary':
  370.                 $ent['data'] .= $cdata;
  371.                 break;
  372.             case 'number':
  373.                 $ent['data'] = $cdata;
  374.                 break;
  375.             case 'boolean':
  376.                 $ent['data'] = $cdata == 'true' ? true : false;
  377.                 break;
  378.                 
  379.             case 'datetime': // not really handled...
  380.                 $ent['data'] = $cdata;
  381.                 break;
  382.             default:
  383.                 return;
  384.             
  385.                 
  386.                 
  387.         }
  388.         $this->_stackTop($ent);
  389.         //echo "C:";print_r(func_get_args());
  390.         //echo "STACK: "; print_r($this->stack);
  391.         //echo "C:";print_r(func_get_args());
  392.     }
  393.     /**
  394.     * expat default handler.
  395.     * 
  396.     * @return   none
  397.     * @access   private
  398.     * @see      XML_Parser::defaultHandler
  399.     */
  400.     function defaultHandler($xp, $cdata) 
  401.     {
  402.         //echo "D:";print_r(func_get_args());
  403.     }
  404.     /**
  405.     * Current indent level.
  406.     *
  407.     * @var array stack
  408.     * @access private
  409.     */
  410.      
  411.     var $_stack = array();
  412.      /**
  413.     * get/set top of stack values..
  414.     * 
  415.     * @param   array optional  (array if it is to be changed..)
  416.     * @return   array|none   (empty parameter = get)
  417.     * @access   private
  418.     */
  419.     function _stackTop($ent = null) 
  420.     {
  421.         
  422.         if ($ent != null) {
  423.             $this->_stack[count($this->_stack)-1] = $ent;
  424.             return;
  425.         }
  426.         if (count($this->_stack)) {
  427.             return  $this->_stack[count($this->_stack)-1];
  428.         
  429.         }
  430.         return;
  431.     }
  432.             
  433.     
  434.     
  435.     
  436. }
  437. /*
  438. // test...
  439. $o = new StdClass;
  440. $o->x = "vvvv";
  441. $ar = array(
  442.     'a' => 1,
  443.     'b' => "TESTING \n 123\n",
  444.     'c' => $o,
  445.     'd' => array('x','y','z')
  446. );
  447. print_r(XML_Wddx::serialize($ar));
  448.  
  449. echo wddx_serialize_value($ar);
  450.  
  451. */